using System;
using System.Collections;
using System.Text;

using PointBridge.SPDX;

namespace HTML
{
	/// <summary>
	/// The AttributeList class is used to store list of
	/// Attribute classes.
	/// This source code may be used freely under the
	/// Limited GNU Public License(LGPL).
	///
	/// Written by Jeff Heaton (http://www.jeffheaton.com)
	/// </summary>
	///
	public class AttributeList:Attribute
	{
		/// <summary>
		/// An internally used Vector.  This vector contains
		/// the entire list of attributes.
		/// </summary>
		protected ArrayList m_list;
		/// <summary>
		/// Make an exact copy of this object using the cloneable
		/// interface.
		/// </summary>
		/// <returns>A new object that is a clone of the specified
		/// object.</returns>
		public override Object Clone()
		{
			AttributeList rtn = new AttributeList();

			for ( int i=0;i<m_list.Count;i++ )
				rtn.Add( (Attribute)this[i].Clone() );

			return rtn;
		}

		/// <summary>
		/// Create a new, empty, attribute list.
		/// </summary>
		public AttributeList():base("","")
		{
			m_list = new ArrayList();
		}


		/// <summary>
		/// Add the specified attribute to the list of attributes.
		/// </summary>
		/// <param name="a">An attribute to add to this
		/// AttributeList.</paramv
		public void Add(Attribute a)
		{
			m_list.Add(a);
		}


		/// <summary>
		/// Clear all attributes from this AttributeList and return
		/// it to a empty state.
		/// </summary>
		public void Clear()
		{
			m_list.Clear();
		}

		/// <summary>
		/// Returns true of this AttributeList is empty, with no
		/// attributes.
		/// </summary>
		/// <returns>True if this AttributeList is empty, false
		/// otherwise.</returns>
		public bool IsEmpty()
		{
			return( m_list.Count<=0);
		}

		/// <summary>
		/// If there is already an attribute with the specified name,
		/// it will have its value changed to match the specified
		/// value. If there is no Attribute with the specified name,
		/// one will be created. This method is case-insensitive.
		/// </summary>
		/// <param name="name">The name of the Attribute to edit or
		/// create.  Case-insensitive.</param>
		/// <param name="value">The value to be held in this
		/// attribute.</param>
		public void Set(string name,string value)
		{
			if ( name==null )
				return;
			if ( value==null )
				value="";

			Attribute a = this[name];

			if ( a==null )

			{
				a = new Attribute(name,value);
				Add(a);
			}

			else
				a.Value = value;
		}

		/// <summary>
		/// How many attributes are in this AttributeList?
		/// </summary>
		public int Count
		{
			get
			{
				return m_list.Count;
			}
		}

		/// <summary>
		/// A list of the attributes in this AttributeList
		/// </summary>
		public ArrayList List
		{
			get
			{
				return m_list;
			}
		}

		/// <summary>
		/// Access the individual attributes
		/// </summary>
		public Attribute this[int index]
		{
			get
			{
				if ( index<m_list.Count )
					return(Attribute)m_list[index];
				else
					return null;
			}
		}

		/// <summary>
		/// Access the individual attributes by name.
		/// </summary>
		public Attribute this[string index]
		{
			get
			{
				int i=0;

				while ( this[i]!=null )
				{
					if ( this[i].Name.ToLower().Equals( (index.ToLower()) )) return this[i];
					i++;
				}
				return null;
			}
        }

        public string GetAttributeValue(string name)
		{
			Attribute attr = this[name];
			if (attr == null) throw new PointBridgeEx("Attribute '" + name + "' does not exist in tag <" + this.Name + ">");
			return attr.Value;
		}

        #region Methods to work with XML
        /*
        public void ReadXMLAttribute(string name, ref Enum val)
        {
            string strVal;
            ReadXMLAttribute(name, out strVal);
            try
            {
                Type type = val.GetType();
                object obj = Enum.Parse(type, strVal);
                val = (Enum)obj;
            }
            catch (Exception ex)
            {
                throw new PointBridgelEx("Unable to parse '" + strVal + "'into " + val.GetType() + " (Name = '" + name + "'): " + ex.Message);
            }
        }
        */        
        public void ReadXMLAttribute(string name, out string val)
        {
            val = System.Web.HttpUtility.HtmlDecode(GetAttributeValue(name));
        }
        public void ReadXMLAttribute(string name, out int val)
        {
            string strVal;
            ReadXMLAttribute(name, out strVal);
            try
            {
                val = int.Parse(strVal);
            }
            catch(Exception ex)
            {
                throw new PointBridgeEx("Unable to parse '" + strVal + "'into int (Name = '" +  name + "'): " + ex.Message);
            }
        }
        public void ReadXMLAttribute(string name, out long val)
        {
            string strVal;
            ReadXMLAttribute(name, out strVal);
            try
            {
                val = long.Parse(strVal);
            }
            catch (Exception ex)
            {
                throw new PointBridgeEx("Unable to parse '" + strVal + "'into long (Name = '" + name + "'): " + ex.Message);
            }
        }
        public void ReadXMLAttribute(string name, out float val)
        {
            string strVal;
            ReadXMLAttribute(name, out strVal);
            try
            {
                val = float.Parse(strVal);
            }
            catch (Exception ex)
            {
                throw new PointBridgeEx("Unable to parse '" + strVal + "'into float (Name = '" + name + "'): " + ex.Message);
            }
        }
        public void ReadXMLAttribute(string name, out bool val)
        {
            string strVal;
            ReadXMLAttribute(name, out strVal);
            try
            {
                val = bool.Parse(strVal);
            }
            catch (Exception ex)
            {
                throw new PointBridgeEx("Unable to parse '" + strVal + "'into bool (Name = '" + name + "'): " + ex.Message);
            }
        }
        public void ReadXMLAttribute(string name, out DateTime val)
        {
            string strVal;
            ReadXMLAttribute(name, out strVal);
            try
            {
                val = DateTime.Parse(strVal);
            }
            catch (Exception ex)
            {
                throw new PointBridgeEx("Unable to parse '" + strVal + "'into DateTime (Name = '" + name + "'): " + ex.Message);
            }
        }
        /*
        public void ReadXMLAttribute(string name, out Enums.Bool val)
        {
            string strVal;
            ReadXMLAttribute(name, out strVal);
            Type type = typeof(Enums.Bool);
            try
            {
                val = (Enums.Bool)Enum.Parse(type, strVal);
            }
            catch (Exception ex)
            {
                throw new PointBridgelEx("Unable to parse '" + strVal + "'into " + type + " (Name = '" + name + "'): " + ex.Message);
            }
        }
        public void ReadXMLAttribute(string name, out Enums.Lates val)
        {
            string strVal;
            ReadXMLAttribute(name, out strVal);
            Type type = typeof(Enums.Lates);
            try
            {
                val = (Enums.Lates)Enum.Parse(type, strVal);
            }
            catch (Exception ex)
            {
                throw new PointBridgelEx("Unable to parse '" + strVal + "'into " + type + " (Name = '" + name + "'): " + ex.Message);
            }
        }
        public void ReadXMLAttribute(string name, out Enums.BkSeasoning val)
        {
            string strVal;
            ReadXMLAttribute(name, out strVal);
            Type type = typeof(Enums.BkSeasoning);
            try
            {
                val = (Enums.BkSeasoning)Enum.Parse(type, strVal);
            }
            catch (Exception ex)
            {
                throw new PointBridgelEx("Unable to parse '" + strVal + "'into " + type + " (Name = '" + name + "'): " + ex.Message);
            }
        }
        public void ReadXMLAttribute(string name, out Enums.FkSeasoning val)
        {
            string strVal;
            ReadXMLAttribute(name, out strVal);
            Type type = typeof(Enums.FkSeasoning);
            try
            {
                val = (Enums.FkSeasoning)Enum.Parse(type, strVal);
            }
            catch (Exception ex)
            {
                throw new PointBridgelEx("Unable to parse '" + strVal + "'into " + type + " (Name = '" + name + "'): " + ex.Message);
            }
        }
        public void ReadXMLAttribute(string name, out Enums.LoanPurpose val)
        {
            string strVal;
            ReadXMLAttribute(name, out strVal);
			
			//this is because we removed Debt consolidation
			switch (strVal)
			{
				case "RefiDebtCons":
					strVal = Enums.LoanPurpose.RefiCashOut.ToString();
					break;
			}
			
			Type type = typeof(Enums.LoanPurpose);
            try
            {
                val = (Enums.LoanPurpose)Enum.Parse(type, strVal);
            }
            catch (Exception ex)
            {
                throw new PointBridgelEx("Unable to parse '" + strVal + "'into " + type + " (Name = '" + name + "'): " + ex.Message);
            }
        }
        public void ReadXMLAttribute(string name, out Enums.LienPosition20 val)
        {
            string strVal;
            ReadXMLAttribute(name, out strVal);

			Type type = typeof(Enums.LienPosition20);
            try
            {
                val = (Enums.LienPosition20)Enum.Parse(type, strVal);
            }
            catch (Exception ex)
            {
                throw new PointBridgelEx("Unable to parse '" + strVal + "'into " + type + " (Name = '" + name + "'): " + ex.Message);
            }
        }
        public void ReadXMLAttribute(string name, out Enums.IncomeDocs20 val)
        {
            string strVal;
            ReadXMLAttribute(name, out strVal);
            Type type = typeof(Enums.IncomeDocs20);
            try
            {
                val = (Enums.IncomeDocs20)Enum.Parse(type, strVal);
            }
            catch (Exception ex)
            {
                throw new PointBridgelEx("Unable to parse '" + strVal + "'into " + type + " (Name = '" + name + "'): " + ex.Message);
            }
        }
        public void ReadXMLAttribute(string name, out Enums.State val)
        {
            string strVal;
            ReadXMLAttribute(name, out strVal);
            Type type = typeof(Enums.State);
            try
            {
                val = (Enums.State)Enum.Parse(type, strVal);
            }
            catch (Exception ex)
            {
                throw new PointBridgelEx("Unable to parse '" + strVal + "'into " + type + " (Name = '" + name + "'): " + ex.Message);
            }
        }
        public void ReadXMLAttribute(string name, out Enums.PropertyType20 val)
        {
			string strVal;
            ReadXMLAttribute(name, out strVal);
			
			//this is because we consolidated PUDS ands and removed
			switch(strVal)
			{
				case "PUDwoHOA":
				case "PUDwithHOA":
					strVal = Enums.PropertyType20.PUD.ToString();
					break;
				case "DWMobileHome":
				case "Modular":
				case "Lot":
				case "LogHome":
					strVal = Enums.PropertyType20.SFR.ToString();
					break;
			}
            
			Type type = typeof(Enums.PropertyType20);
            try
            {
                val = (Enums.PropertyType20)Enum.Parse(type, strVal);
            }
			catch (Exception ex)
            {
                throw new PointBridgelEx("Unable to parse '" + strVal + "'into " + type + " (Name = '" + name + "'): " + ex.Message);
            }
        }
        public void ReadXMLAttribute(string name, out Enums.Occupancy val)
        {
            string strVal;
            ReadXMLAttribute(name, out strVal);
            Type type = typeof(Enums.Occupancy);
            try
            {
                val = (Enums.Occupancy)Enum.Parse(type, strVal);
            }
            catch (Exception ex)
            {
                throw new PointBridgelEx("Unable to parse '" + strVal + "'into " + type + " (Name = '" + name + "'): " + ex.Message);
            }
        }
        public void ReadXMLAttribute(string name, out Enums.NumOfUnits val)
        {
            string strVal;
            ReadXMLAttribute(name, out strVal);
            Type type = typeof(Enums.NumOfUnits);
            try
            {
                val = (Enums.NumOfUnits)Enum.Parse(type, strVal);
            }
            catch (Exception ex)
            {
                throw new PointBridgelEx("Unable to parse '" + strVal + "'into " + type + " (Name = '" + name + "'): " + ex.Message);
            }
        }
        public void ReadXMLAttribute(string name, out Enums.LoanType val)
        {
            string strVal;
            ReadXMLAttribute(name, out strVal);
            Type type = typeof(Enums.LoanType);
            try
            {
                val = (Enums.LoanType)Enum.Parse(type, strVal);
            }
            catch (Exception ex)
            {
                throw new PointBridgelEx("Unable to parse '" + strVal + "'into " + type + " (Name = '" + name + "'): " + ex.Message);
            }
        }
        public void ReadXMLAttribute(string name, out Enums.Prepay val)
        {
            string strVal;
            ReadXMLAttribute(name, out strVal);
            Type type = typeof(Enums.Prepay);
            try
            {
                val = (Enums.Prepay)Enum.Parse(type, strVal);
            }
            catch (Exception ex)
            {
                throw new PointBridgelEx("Unable to parse '" + strVal + "'into " + type + " (Name = '" + name + "'): " + ex.Message);
            }
        }
		public void ReadXMLAttribute(string name, out Enums.ProgramCat val)
		{
			string strVal;
			ReadXMLAttribute(name, out strVal);
			if (strVal == "Portfolio") strVal = Enums.ProgramCat.AltA.ToString();

			Type type = typeof(Enums.ProgramCat);
			try
			{
				val = (Enums.ProgramCat)Enum.Parse(type, strVal);
			}
			catch (Exception ex)
			{
				throw new PointBridgelEx("Unable to parse '" + strVal + "'into " + type + " (Name = '" + name + "'): " + ex.Message);
			}
		}
		public void ReadXMLAttribute(string name, out LoanProduct20.ArmType val)
		{
			string strVal;
			ReadXMLAttribute(name, out strVal);
			Type type = typeof(LoanProduct20.ArmType);
			try
			{
				val = (LoanProduct20.ArmType)Enum.Parse(type, strVal);
			}
			catch (Exception ex)
			{
				throw new PointBridgelEx("Unable to parse '" + strVal + "'into " + type + " (Name = '" + name + "'): " + ex.Message);
			}
		}
        */
        public void AddXMLAttribute(string name, string val)
        {
            Add(new Attribute(name, System.Web.HttpUtility.HtmlEncode(val)));
        }
        public void AddXMLAttribute(string name, int val)
        {
            AddXMLAttribute(name, val.ToString());
        }
        public void AddXMLAttribute(string name, long val)
        {
            AddXMLAttribute(name, val.ToString());
        }
        public void AddXMLAttribute(string name, float val)
        {
            AddXMLAttribute(name, val.ToString());
        }
        public void AddXMLAttribute(string name, bool val)
        {
            AddXMLAttribute(name, val.ToString());
        }
        public void AddXMLAttribute(string name, DateTime val)
        {
            AddXMLAttribute(name, val.ToString());
        }
        public void AddXMLAttribute(string name, Enum val)
        {
            //AddXMLAttribute(name, (byte)Convert.ChangeType(val, Enum.GetUnderlyingType(val.GetType())));
            AddXMLAttribute(name, val.ToString());
        }

        public string ToXMLString(bool close)
		{
            StringBuilder strTag = new StringBuilder();
            strTag.Append("<" + Name + " ");
            for (int i = 0; i < Count; i++)
            {
                strTag.Append(this[i].Name + "=\"" + this[i].Value + "\" ");
            }
            if (close == true) strTag.Append("/");
            strTag.Append(">\n");
            return strTag.ToString();		    
		}

	    public string ToClosingXMLString()
	    {
	        return GetSimpleXMLTag("/" + Name);
	    }

        public static string GetSimpleXMLTag(string name)
        {
            return "<" + name + ">\n";
        }
        #endregion


	}
}

